Spring MVC入门案例
Spring MVC入门案例
入门案例
-
导入SpringMVC坐标与Servlet坐标
<dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>3.1.0</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.springframework</groupId> <artifactId>spring-webmvc</artifactId> <version>5.2.10.RELEASE</version> </dependency>
注意事项:
导入spring-webmvc坐标自动依赖spring相关坐标 -
初始化SpringMVC环境(同Spring环境)
@Configuration public class SpringMvcConfig { }
-
创建SpringMVC控制器类(等同于Servlet功能)
@Controller public class UserController { @RequestMapping("/save") public String save(){ System.out.println("user save ..."); return "{'info':'springmvc'}"; } }
-
设定SpringMVC加载对应的bean
@Configuration @ComponentScan("com.charley.controller") public class SpringMvcConfig { }
-
初始化Servlet容器,加载SpringMVC环境,并设置SpringMVC请求拦截的路径
public class ServletContainerInitConfig extends AbstractDispatcherServletInitializer { @Override // 加载springmvc对应的容器对象 protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringMvcConfig.class); return ctx; } @Override // 哪些请求归mvc处理 protected String[] getServletMappings() { return new String[]{"/"}; // 表示所有的请求都归springmvc处理 } @Override // 加载的是spring对应的容器对象 protected WebApplicationContext createRootApplicationContext() { return null; } }
-
使用浏览器测试请求。
注意事项:由于为设定请求执行后响应的页面信息,页面显示空白,后台输出代码正常运行。 -
设定请求方法的返回值为字符串类型,并返回自定义的json数据
@Controller public class UserController { @RequestMapping("/save") @ResponseBody public String save(){ System.out.println("user save ..."); return "{'info':'springmvc'}"; } }
-
使用浏览器测试请求,请求测试成功
案例中使用到的注解含义
-
名称:@Controller
-
类型:类注解
-
位置:SpringMVC控制器类定义上方
-
作用:设定SpringMVC的核心控制器bean
-
范例:
@Controller public class UserController{ }
-
名称:@RequestMapping
-
类型:方法注解
-
位置:SpringMVC控制器方法定义上方
-
作用:设置当前控制器方法请求访问的路径
-
范例:
@RequestMapping("/save") public void save(){ System.out.println("user save ..."); }
-
相关属性:
- value(默认):请求访问路径
-
名称:@ResponseBody
-
类型:方法注解
-
位置:SpringMVC控制器方法定义上方
-
作用:设置当前控制器方法响应内容为当前返回值,无需解析
-
范例:
@RequestMapping("/save") @ResponseBody public void save(){ System.out.println("user save ..."); return "{'info':'springmvc'}"; }
-
AbstractDispatcherServletInitializer类是SpringMVC提供的快速初始化Web3.0容器的抽象类。
-
AbstractDispatcherServletInitializer提供三个接口方法供用户实现
-
createServletApplicationContext()方法,创建Servlet容器时,加载SpringMVC对应的bean并放入WebApplicationContext对象范围中,而WebApplicationContext的作用范围为ServletContext范围,即整个Web容器范围
protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringMvcConfig.class); return ctx; }
-
getServletMapping()方法,设定SpringMVC对应的请求映射路径,设置为/表示拦截所有请求,任意请求都将转入到SpringMVC进行处理
@Override // 哪些请求归mvc处理 protected String[] getServletMappings() { return new String[]{"/"}; // 表示所有的请求都归springmvc处理 }
-
createRootApplicationContext()方法,如果创建Servlet容器时需要加载非SpringMVC对应的bean,使用当前方法进行,使用方式同createServletApplicationContext()
@Override // 加载的是spring对应的容器对象 protected WebApplicationContextcreateRootApplicationContext() { return null; }
-
入门案例开发总结
- 一次性工作
- 创建工程,设置服务器,加载工程
- 导入坐标
- 创建web容器启动类,加载SpringMVC配置,并设置SpringMVC请求拦截路径
- SpringMVC核心配置类(设置配置类,扫描controller包,加载Controller控制器bean)
- 多次工作
- 定义处理请求的控制器类
- 定义处理请求的控制器方法,并配置映射路径(@RequestMapping)与返回json数据(@ResponseBody)
入门案例工作流程分析
启动服务器初始化过程
-
服务器启动,执行ServletContainersInitConfig类,初始化web容器
-
执行createServletApplicationContext方法,创建了WebApplicationContext对象
-
加载SpringMvcConfig
-
执行@CompoentScan加载对应的bean
-
加载UserController, 每个@RequestMapping的名称对应一个具体的方法
-
执行getServletMapping方法,定义所有的请求都通过SpringMVC
单次请求过程
- 发送请求localhost/save
- Web容器发现所有请求都经过SpringMVC,将请求交给SpringMVC处理
- 解析请求路径/save
- 由/save匹配执行对应的方法save()
- 执行save()
- 检测到有@ResponseBody直接将save()方法的返回值作为响应求体返回给请求方
Controller加载控制与业务bean加载控制
- SpringMVC相关bean(表现层bean)
- Spring控制的bean
- 业务层bean(Service)
- 功能bean(DataSource等)
思考:因为功能不同,如何避免Spring错误的加载到SpringMVC的bean。
加载Spring控制的bean的时候,排除掉SpringMVC控制的bean
- SpringMVC相关bean加载控制
- SpringMVC加载的bean对应的包均在com.charley.controller包内
- Spring相关bean加载控制
- 方式一:Spring加载的bean设定扫描范围为com.charley. 排除掉controller包内的bean
- 方式二:Spring加载的bean设定扫描范围为精准范围,例如service包、dao包等
- 方式三:不区分Spring与SpringMVC的环境,加载到同一个环境中
@Configuration
// 方式一
//@ComponentScan({"com.charley.service","com.charley.dao"}) // 建立把dao包写上,适配所有的数据层技术
// 方式二
@ComponentScan(value="com.charley",
excludeFilters = @ComponentScan.Filter(
type = FilterType.ANNOTATION,
classes = Controller.class
)
)
public class SpringConfig {
}
-
名称: @ComponentScan
-
类型:类注解
-
范例
@ComponentScan(value="com.charley", excludeFilters = @ComponentScan.Filter( type = FilterType.ANNOTATION, classes = Controller.class ) )
-
属性
- excludeFilters: 排除扫描路径中加载的bean,需要指定类别(type)与具体项(classes)
- includeFilters: 加载指定的bean,需要指定类别(type)与具体项(classes)
-
bean的加载格式
public class ServletContainersInitConfig extends AbstractDispatcherServletInitializer { @Override protected WebApplicationContext createServletApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringMvcConfig.class); return ctx; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } @Override protected WebApplicationContext createRootApplicationContext() { AnnotationConfigWebApplicationContext ctx = new AnnotationConfigWebApplicationContext(); ctx.register(SpringConfig.class); return ctx; } }
-
简化开发
public class ServletContainersInitConfig extends AbstractAnnotationConfigDispatcherServletInitializer{ @Override protected Class<?>[] getRootConfigClasses() { return new Class[]{SpringMvcConfig.class}; } @Override protected Class<?>[] getServletConfigClasses() { return new Class[]{SpringConfig.class}; } @Override protected String[] getServletMappings() { return new String[]{"/"}; } }